// 1 class 的基本用法 继承 和 类型约束 implements
// 2 class 的修饰符 
  /* 
  readonly 只修饰属性
  private 属性和方法都可以    只能自己内部使用        私有化
  protected 属性和方法都可以  只能子类和自己内部使用   私有化
  public  属性和方法都可以    哪都能用                公有化  默认都是公有化
  */
// 3 super 原理
// 4 静态方法
// 5 get set

interface Options {
  el: string | HTMLElement
}

interface VueCls {
  options: Options
  init(): void
}

interface Vnode {
  tag: string
  text?: string
  children?: Vnode[]
}

// 虚拟dom 简单版
class Dom {
  constructor(name: string) {

  }
  // 创建节点的方法
  createElement(el:string) {
    return document.createElement(el)
  }
  // 填充文本的方法
  setText(el: HTMLElement, text:string | null) {
    el.textContent = text;
  }
  // 渲染函数
  render(data: Vnode) {
    let root = this.createElement(data.tag)
    if(data.children && Array.isArray(data.children)) {
      data.children.forEach(item => {
        let child = this.render(item)
        root.appendChild(child)
      })
    } else {
      this.setText(root, String(data.text))
    }

    return root
  }
}

class Vue extends Dom implements VueCls { // 对类进行约束
  options: Options
  constructor(options: Options) {
    // 调用父类构造函数
    // 父类.prototype.constructor.call
    super("老李")
    this.options = options
    this.init()
  }

  static xxx() {}

  static version() {
    this.xxx()      // 静态调用静态方法和属性
    // this.init()  // 不能调用子类的静态方法
    return "1.0.0"
  }

  public init(): void {
    console.log('init')
    // 虚拟dom 就是通过js 去渲染我们这个真实dom
    let data:Vnode = {
      tag: 'div',
      children: [
        { 
          tag: 'seciton',
          text: '我是子节点1'
        },
        { 
          tag: 'seciton',
          text: '我是子节点2'
        },
        {
          tag: 'seciton',
          text: '我是子节点3'
        }
      ]
    }

    let app = typeof this.options.el === "string" ? document.querySelector(this.options.el) : this.options.el
    app?.appendChild(this.render(data))
  }
}

new Vue({
  el: '#app'
})

// Promise.all // 静态方法  不需要new Promise()
Vue.version()

class Ref {
  _value: any
  constructor(value: any) {
    this._value = value
  }

  get value() {
    return this._value + "xxx"
  }

  set value(newValue) {
    this._value = newValue + "老李"
  }
}

const ref = new Ref("哈哈哈哈哈，是你啊，")
console.log(ref.value)
ref.value = "我还是我"
console.log(ref.value)